//
//  MQmanager.m
//  YKRabbitMQSDK
//
//  Created by edward on 2020/6/14.
//  Copyright © 2020 edward. All rights reserved.
//

#import "MQManager.h"
#import <RMQClient/RMQClient.h>


@interface MQManager()<RMQConnectionDelegate>
///
@property (nonatomic,strong) RMQConnection *conn;
///
@property(nonatomic,copy) NSString *path;
///
@property(nonatomic,copy) NSString *user;
///
@property(nonatomic,copy) NSString *password;
///
@property(nonatomic,copy) NSArray<NSString *> *exchangeNames;
///
@property(nonatomic,strong)NSArray<MQKey *> *routingkeys;
///代理器
@property(nonatomic,weak) id<MQManagerDelegate> delegate;

@end

@implementation MQManager

- (instancetype)init
{
    self = [super init];
    if (self) {
        
        [[NSNotificationCenter defaultCenter] postNotificationName:@"kIncludeMQ" object:@{@"include":@(YES)}];
    }
    return self;
}

+ (instancetype)loginUser:(NSString *)user password:(NSString *)password path:(NSString *)path exchangeNames:(NSArray<NSString *> *)exchangeNames routingKeys:(NSArray<MQKey *> *)routingKeys delegate:(id<MQManagerDelegate>)delegate
{
    MQManager *manager = [[MQManager alloc] init];
    manager.user = user;
    manager.password = password;
    manager.path = path;
    manager.routingkeys = routingKeys;
    manager.exchangeNames = exchangeNames;
    manager.conn = [[RMQConnection alloc] initWithUri:[NSString stringWithFormat:@"amqp://%@:%@@%@",user,password,manager.path] delegate:manager];
    manager.delegate = delegate;
    return manager;
}

/**使用guest默认游客登录mq*/
+ (instancetype)loginPath:(NSString *)path exchangeNames:(NSArray<NSString *> *)exchangeNames routingKeys:(NSArray<MQKey *> *)routingKeys delegate:(id<MQManagerDelegate>)delegate
{
    return [self loginUser:@"guest" password:@"guest" path:path exchangeNames:exchangeNames routingKeys:routingKeys delegate:delegate];
}

/**默认使用单一exchangeName*/
+ (instancetype)loginUser:(NSString *)user password:(NSString *)password path:(NSString *)path routingKeys:(NSArray<MQKey *> *)routingKeys delegate:(id<MQManagerDelegate>)delegate
{
    return [self loginUser:user password:password path:path exchangeNames:@[@"exchange"] routingKeys:routingKeys delegate:delegate];
}

/**默认使用游客以及单一exchangeName（最轻量）*/
+ (instancetype)loginPath:(NSString *)path routingKeys:(NSArray<MQKey *> *)routingKeys delegate:(id<MQManagerDelegate>)delegate
{
    return [self loginUser:@"guest" password:@"guest" path:path exchangeNames:@[@"exchange"] routingKeys:routingKeys delegate:delegate];
}

- (void)getMsg{
    if (self.conn) {
        [self receiveLogsTopic];
    }else
    {
#ifdef DEBUG
        NSLog(@"/*****🚀请先初始化MQManager或账号密码错误链接失败🚀*****/");
#endif
    }
}


- (void)sendNorMsg:(NSString *)msg key:(MQKey *)key
{
    [self sendMsg:msg exchangeName:@"exchange" AndKey:key];
}

- (void)sendMsg:(NSString *)msg exchangeName:(NSString *)exchangeName AndKey:(MQKey *)key{
    [self emitLogTopic:msg exchangeName:exchangeName sendKey:key];
}

- (void)emitLogTopic:(NSString *)msg exchangeName:(NSString *)exchangeName sendKey:(MQKey *)sendKey {
    
//    RMQConnection *con = [[RMQConnection alloc] initWithUri:[NSString stringWithFormat:@"amqp://%@:%@@%@",self.user,self.password,self.path] delegate:self];
//    [con start];
//    id<RMQChannel> ch = [con createChannel];
//    /** 创建交换器 */
//    RMQExchange *x    = [ch topic:exchangeName];
    RMQExchange *x = [[self.conn createChannel] topic:exchangeName];
    [x publish:[msg dataUsingEncoding:NSUTF8StringEncoding] routingKey:[sendKey getMqKeyStr]];
//    [con close];
    
}

- (void)receiveLogsTopic{
    /** 创建连接 */
    [self.conn start];

    /** 创建信道 */
    id<RMQChannel> ch = [self.conn createChannel];
    RMQQueue *q       = [ch queue:[NSString stringWithFormat:@"ios_%@",[[NSUUID UUID] UUIDString]] options:RMQQueueDeclareExclusive];
    
    [self.exchangeNames enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        /** 创建交换器 */
        RMQExchange *x    = [ch topic:obj];
        /** 绑定交换器 */
        __weak typeof(x) weakX = x;
        __weak typeof(q) weakQ = q;
        [self.routingkeys enumerateObjectsUsingBlock:^(MQKey * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            NSString *key = [obj getMqKeyStr];
            [weakQ bind:weakX routingKey:key];
        }];
    }];
    
#ifdef DEBUG
    NSLog(@"Waiting for logs.");
#endif
            
    /** 订阅消息 */
    __weak typeof(self) weakself = self;
    [q subscribe:^(RMQMessage * _Nonnull message) {
        __weak typeof(weakself) strongself = weakself;
        NSDateFormatter *format = [[NSDateFormatter alloc] init];
        [format setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
        [format setTimeZone:[NSTimeZone systemTimeZone]];
        NSDate *nowDate = [NSDate date];
        if (strongself.delegate && [strongself.delegate respondsToSelector:@selector(mqmanager:receiveMessageData:routingKey:consumerTag:exchangeName:receiveDate:)]) {
            [strongself.delegate mqmanager:strongself receiveMessageData:message.body routingKey:message.routingKey consumerTag:message.consumerTag exchangeName:message.exchangeName receiveDate:[format stringFromDate:nowDate]];
        }
#ifdef DEBUG
        //发送debug消息给debugmanager
        NSDictionary *messageDic = @{
            @"body":message.body?:[NSData data],
            @"routingKey":message.routingKey?:@"",
            @"consumerTag":message.consumerTag?:@"",
            @"exchangeName":message.exchangeName?:@"",
            @"receiveDate":nowDate
        };
        [[NSNotificationCenter defaultCenter] postNotificationName:@"debug_mqmanager" object:nil userInfo:messageDic];
#endif
    }];
    
}
- (void)endConnection
{
    if (self.conn) {
        [self.conn close];
    }
}
- (BOOL)mqIsClosd
{
    return (self.conn && !self.conn.isOpen);
}

#pragma mark RMQConnectionDelegate

/// 连接过程中，信道异常调用
- (void)channel:(id<RMQChannel>)channel error:(NSError *)error {
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:onError:errorType:)]) {
        [self.delegate mqmanager:self onError:error errorType:MQManagerErrorTypeConnectAbnormal];
    }
}

/// 没有连接成功回调
- (void)connection:(RMQConnection *)connection disconnectedWithError:(NSError *)error {
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:onError:errorType:)]) {
        [self.delegate mqmanager:self onError:error errorType:MQManagerErrorTypeConnectFaild];
    }
}
///socket 连接失败回调，超时或者地址有误
- (void)connection:(RMQConnection *)connection failedToConnectWithError:(NSError *)error {
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:onError:errorType:)]) {
        [self.delegate mqmanager:self onError:error errorType:MQManagerErrorTypeOverTimeOrAddressError];
    }
}

/// 已经恢复连接的时候，调用
- (void)recoveredConnection:(RMQConnection *)connection {
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:recoveredConnectionType:)]) {
        [self.delegate mqmanager:self recoveredConnectionType:MQManagerRecoveredTypeFinish];
    }
}

/// 正在开始恢复连接
- (void)startingRecoveryWithConnection:(RMQConnection *)connection {
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:recoveredConnectionType:)]) {
        [self.delegate mqmanager:self recoveredConnectionType:MQManagerRecoveredTypeStarting];
    }
}

/// 自动 
- (void)willStartRecoveryWithConnection:(RMQConnection *)connection {
    if (self.delegate && [self.delegate respondsToSelector:@selector(mqmanager:recoveredConnectionType:)]) {
        [self.delegate mqmanager:self recoveredConnectionType:MQManagerRecoveredTypeWillStart];
    }
}

- (void)dealloc
{
    if (_conn) {
        [_conn close];
        _conn = nil;
    }
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    NSLog(@"🔥mqmanger:%@",@"dealloc");
}

#pragma mark set/get
- (NSArray<MQKey *> *)routingkeys
{
    if(!_routingkeys)
    {
        _routingkeys = [NSArray array];
    }
    return _routingkeys;
}
@end

